﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using RPGOnline.Controls.Map.Events;
using RPGOnline.Controls.Map.Layers;
using RPGOnline.Properties;
using RPGOnline.Rendering;

namespace RPGOnline.Controls.Map
{
    public partial class MapDrawerControl : UserControl
    {
        private Map m_map;
        private BackgroundLayer m_backgroundLayer;
        private GridLayer m_gridLayer;
	    private Renderer m_renderer;
	    private bool m_showLights = false;
	    public event EventHandler<CellEventArgs> OnCellMouseDown;
        public event EventHandler<CellEventArgs> OnCellMouseMove;
        public event EventHandler<CellEventArgs> OnCellMouseUp;

        public MapDrawerControl()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, false);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
            SetStyle(ControlStyles.ResizeRedraw, false);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        	SetStyle(ControlStyles.Opaque, true);
			SetStyle(ControlStyles.SupportsTransparentBackColor, false);

            InitializeComponent();

	        m_renderer = new Renderer(this);
        }

        public Map Map 
        { 
            get
            {
                return m_map;
            } 
            set
            {
                m_map = value;
                if (m_map == null)
                    return;

                Width = m_map.MapSize.Width*m_map.TileSize.Width;
                Height = m_map.MapSize.Height*m_map.TileSize.Height;

	            m_renderer.Initialize();

				m_backgroundLayer = new BackgroundLayer(m_renderer, m_map);
				m_gridLayer = new GridLayer(m_renderer, m_map);
            } 
        }

	    public MapLayer OverlayLayer
	    {
		    get
		    {
			    return m_map.OverlayLayer;
		    }
	    }

	    [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool GridVisible
        {
            get { return m_gridLayer.Visible; }
            set { m_gridLayer.Visible = value; }
        }

	    public Renderer Renderer { get { return m_renderer; } }

	    protected override void OnPaint(PaintEventArgs e)
        {
            if (m_map == null)
                return;

		    if (m_showLights)
		    {
			    using (m_renderer.BeginFirstPass())
			    {
				    m_renderer.Clear(Color.Yellow);
				    m_backgroundLayer.Draw();
				    m_map.DrawLayers();
			    }

			    m_map.UpdateLighting();

			    using (m_renderer.BeginSecondPass())
			    {
				    m_renderer.Clear(Color.Black);

				    m_map.DrawAmbient();
				    m_map.DrawLighting();

				    m_map.DrawOverlay();
				    m_gridLayer.Draw();
			    }
		    }
		    else
		    {
				using (m_renderer.BeginSecondPass())
				{
					m_renderer.Clear(Color.Black);
					m_backgroundLayer.Draw();
					m_map.DrawLayers();
					m_map.DrawLights();
					m_map.DrawOverlay();
					m_gridLayer.Draw();
				}
		    }

		    m_renderer.Render();
        }

    	protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (m_map == null)
                return;

            int x = e.X/m_map.TileSize.Width;
            int y = e.Y/m_map.TileSize.Height;

            if(x < 0 || x >= m_map.MapSize.Width || y < 0 || y >= m_map.MapSize.Height)
                return;

            if (OnCellMouseDown != null)
                OnCellMouseDown(this, new CellEventArgs(e, new Point(x,y)));
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (m_map == null)
                return;

            int x = e.X / m_map.TileSize.Width;
            int y = e.Y / m_map.TileSize.Height;

            if (x < 0 || x >= m_map.MapSize.Width || y < 0 || y >= m_map.MapSize.Height)
                return;

            if (OnCellMouseMove != null)
                OnCellMouseMove(this, new CellEventArgs(e, new Point(x, y)));
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            if (m_map == null)
                return;

            int x = e.X / m_map.TileSize.Width;
            int y = e.Y / m_map.TileSize.Height;

            if (x < 0 || x >= m_map.MapSize.Width || y < 0 || y >= m_map.MapSize.Height)
                return;

            if (OnCellMouseUp != null)
                OnCellMouseUp(this, new CellEventArgs(e, new Point(x, y)));
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Invalidate();
        }

	    public void ToggleShowLights()
	    {
		    m_showLights = !m_showLights;
	    }
    }
}
